/**
 *  Copyright 2002-2009 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package foo.bar.blog.web.action;

import java.util.Date;

/**
 * Represents a particular date in the calendar. Day, Month and Year could be set, if they are not, it will
 * default to today's Day, month or year respectively. 
 *
 * @author tmjee
 * @version $Date: 2009-03-14 06:53:07 +0000 (Sat, 14 Mar 2009) $ $Id$
 */
public class Calendar {

    private DayEnum day;
    private MonthEnum month;
    private int year;


    /**
     * Make this calendar represents today's date.
     */
    public void setTimeAsNow() {
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        calendar.setTime(new Date());

        day = DayEnum.convert(calendar.get(java.util.Calendar.DAY_OF_MONTH));
        month = MonthEnum.convert(calendar.get(java.util.Calendar.MONTH));
        year = calendar.get(java.util.Calendar.YEAR);
    }

    /**
     * Get today's day
     * @return {@link DayEnum}
     */
    public DayEnum getDay() {
        return day;
    }

    /**
     * Set today's day
     * @param day
     */
    public void setDay(DayEnum day) {
        this.day = day;
    }


    /**
     * Get today's month
     * @return {@link foo.bar.blog.web.action.MonthEnum}
     */
    public MonthEnum getMonth() {
        return month;
    }

    /**
     * Set today's month
     * @param month
     */
    public void setMonth(MonthEnum month) {
        this.month = month;
    }

    /**
     * Get today's year.
     * @return int
     */
    public int getYear() {
        return year;
    }

    /**
     * Set today's year.
     * @param year
     */
    public void setYear(int year) {
        this.year = year;
    }

    /**
     * Get the first day of the month for the day this calendar repersents.
     * @return {@link java.util.Date}
     */
    public Date getStartDate() {
        java.util.Calendar now = java.util.Calendar.getInstance();
        now.setTime(new Date());
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        if (day == null) {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, DayEnum.DAY1.day());
        }
        else {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, day.day());
        }
        if (month == null) {
            calendar.set(java.util.Calendar.MONTH, now.get(java.util.Calendar.MONTH));
        }
        else {
            calendar.set(java.util.Calendar.MONTH, month.month());
        }
        if (year <= 0) {
            calendar.set(java.util.Calendar.YEAR, now.get(java.util.Calendar.YEAR));
        }
        else {
            calendar.set(java.util.Calendar.YEAR, year);
        }
        calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
        calendar.set(java.util.Calendar.MINUTE, 0);
        calendar.set(java.util.Calendar.SECOND, 0);
        calendar.set(java.util.Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * Get the last day of the month of which this calendar day represents.
     * @return {@link java.util.Date}
     */
    public Date getEndDate() {
        java.util.Calendar now = java.util.Calendar.getInstance();
        now.setTime(new Date());
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        if (day == null) {
            // calculate the last day :-
            java.util.Calendar tmp = java.util.Calendar.getInstance();
            tmp.set(java.util.Calendar.DAY_OF_MONTH, 1);
            if (month == null) {
                tmp.set(java.util.Calendar.MONTH, now.get(java.util.Calendar.MONTH));
            }
            else {
                tmp.set(java.util.Calendar.MONTH, month.month());
            }
            if (year <= 0) {
                tmp.set(java.util.Calendar.YEAR, now.get(java.util.Calendar.YEAR));
            }
            else {
                tmp.set(java.util.Calendar.YEAR, year);
            }
            tmp.add(java.util.Calendar.MONTH, 1);
            tmp.add(java.util.Calendar.DAY_OF_MONTH, -1); // now we have the last day

            calendar.set(java.util.Calendar.DAY_OF_MONTH, tmp.get(java.util.Calendar.DAY_OF_MONTH));
        }
        else {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, day.day());
        }
        if (month == null) {
            calendar.set(java.util.Calendar.MONTH, now.get(java.util.Calendar.MONTH));
        }
        else {
            calendar.set(java.util.Calendar.MONTH, month.month());
        }
        if (year <= 0) {
            calendar.set(java.util.Calendar.YEAR, now.get(java.util.Calendar.YEAR));
        }
        else {
            calendar.set(java.util.Calendar.YEAR, year);
        }
        calendar.set(java.util.Calendar.HOUR_OF_DAY, 23);
        calendar.set(java.util.Calendar.MINUTE, 59);
        calendar.set(java.util.Calendar.SECOND, 59);
        calendar.set(java.util.Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    /**
     * Get the next day this calendar date represents.
     * @return {@link java.util.Date}
     */
    public Date getNextDate() {
        java.util.Calendar now = java.util.Calendar.getInstance();
        now.setTime(new Date());
        java.util.Calendar calendar = java.util.Calendar.getInstance();

        if (day != null) {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, day.day());
        }
        else {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, 1);
        }
        if (month != null) {
            calendar.set(java.util.Calendar.MONTH, month.month());
        }
        else {
            calendar.set(java.util.Calendar.MONTH, now.get(java.util.Calendar.MONTH));
        }
        if (year > 0) {
            calendar.set(java.util.Calendar.YEAR, year);
        }
        else {
            calendar.set(java.util.Calendar.YEAR,  now.get(java.util.Calendar.YEAR));
        }
        calendar.add(java.util.Calendar.MONTH, 1);
        calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
        calendar.set(java.util.Calendar.MINUTE, 0);
        calendar.set(java.util.Calendar.SECOND, 0);
        calendar.set(java.util.Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * Get the previous day this calendar date represents.
     * @return {@link java.util.Date}
     */
    public Date getPreviousDate() {
        java.util.Calendar now = java.util.Calendar.getInstance();
        now.setTime(new Date());
        java.util.Calendar calendar = java.util.Calendar.getInstance();

        if (day != null) {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, day.day());
        }
        else {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, 1);
        }
        if (month != null) {
            calendar.set(java.util.Calendar.MONTH, month.month());
        }
        else {
            calendar.set(java.util.Calendar.MONTH, now.get(java.util.Calendar.MONTH));
        }
        if (year > 0) {
            calendar.set(java.util.Calendar.YEAR, year);
        }
        else {
            calendar.set(java.util.Calendar.YEAR,  now.get(java.util.Calendar.YEAR));
        }
        calendar.add(java.util.Calendar.MONTH, -1);
        calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
        calendar.set(java.util.Calendar.MINUTE, 0);
        calendar.set(java.util.Calendar.SECOND, 0);
        calendar.set(java.util.Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    /**
     * Get the day this calendar date represents as {@link java.util.Date}.
     * @return {@link java.util.Date}
     */
    public Date getAsDate() {
        java.util.Calendar now = java.util.Calendar.getInstance();
        now.setTime(new Date());
        java.util.Calendar calendar = java.util.Calendar.getInstance();

        if (day != null) {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, day.day());
        }
        else {
            calendar.set(java.util.Calendar.DAY_OF_MONTH, 1);
        }
        if (month != null) {
            calendar.set(java.util.Calendar.MONTH, month.month());
        }
        else {
            calendar.set(java.util.Calendar.MONTH, now.get(java.util.Calendar.MONTH));
        }
        if (year > 0) {
            calendar.set(java.util.Calendar.YEAR, year);
        }
        else {
            calendar.set(java.util.Calendar.YEAR,  now.get(java.util.Calendar.YEAR));
        }
        calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
        calendar.set(java.util.Calendar.MINUTE, 0);
        calendar.set(java.util.Calendar.SECOND, 0);
        calendar.set(java.util.Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * to string representation of this calendar day.
     * @return String
     */
    public String toString() {
        return "[day="+(day==null?"null":day.name())+",month="+(month==null?"null":month.name())+"year="+year+"]";
    }
}
